home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / iproc-pi.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  6KB  |  291 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* NOTE WELL:
  9.  * This file is "included" into iproc.c -- it is not compiled separately!
  10.  */
  11.  
  12. #include <signal.h>
  13. #include <sgtty.h>
  14. #include "wait.h"
  15.  
  16. #define DEAD    1    /* Dead but haven't informed user yet */
  17. #define STOPPED    2    /* Job stopped */
  18. #define RUNNING    3    /* Just running */
  19. #define NEW    4    /* This process is brand new */
  20.  
  21. /* If process is dead, flags says how. */
  22. #define EXITED    1
  23. #define KILLED    2
  24.  
  25. #define isdead(p)    ((p) == NULL || proc_state((p)) == DEAD || (p)->p_toproc == -1)
  26. #define makedead(p)    { proc_state((p)) = DEAD; }
  27.  
  28. #define proc_buf(p)    ((p)->p_buffer->b_name)
  29. #define proc_cmd(p)    ((p)->p_name)
  30. #define proc_state(p)    ((p)->p_state)
  31.  
  32. private Process    *procs = NULL;
  33.  
  34. File    *ProcInput;
  35. int    ProcOutput,
  36.     kbd_pid = 0,
  37.     NumProcs = 0;
  38.  
  39. private Process *
  40. proc_pid(pid)
  41. int    pid;
  42. {
  43.     register Process    *p;
  44.  
  45.     for (p = procs; p != NULL; p = p->p_next)
  46.         if (p->p_portpid == pid)
  47.             break;
  48.  
  49.     return p;
  50. }
  51.  
  52. void
  53. read_proc(pid, nbytes)
  54. int    pid;
  55. register int    nbytes;
  56. {
  57.     register Process    *p;
  58.     char    ibuf[512];
  59.  
  60.     if ((p = proc_pid(pid)) == NULL) {
  61.         writef("\riproc: unknown pid (%d)", pid);
  62.         return;
  63.     }
  64.  
  65.     if (proc_state(p) == NEW) {
  66.         int    rpid;
  67.         /* pid of real child, not of portsrv */
  68.  
  69.         (void) f_readn(ProcInput, (char *) &rpid, sizeof (int));
  70.         p->p_pid = rpid;
  71.         p->p_state = RUNNING;
  72.         return;
  73.     }
  74.  
  75.     if (nbytes == EOF) {        /* okay to clean up this process */
  76.         union wait    status;
  77.         int    pid;
  78.  
  79.         (void) f_readn(ProcInput, &status.w_status, sizeof (int));
  80.         do {
  81.             pid = wait((int *)NULL);
  82.             if (pid < 0)
  83.                 break;
  84.             kill_off(pid, status);
  85.         } while (pid != p->p_portpid);
  86.         proc_close(p);
  87.         makedead(p);
  88.         return;
  89.     }
  90.  
  91.     while (nbytes > 0) {
  92.         size_t n = f_readn(ProcInput, ibuf, min((sizeof ibuf) - 1, nbytes));
  93.  
  94.         ibuf[n] = '\0';    /* Null terminate for convenience */
  95.         nbytes -= n;
  96.         proc_rec(p, ibuf);
  97.     }
  98. }
  99.  
  100. void
  101. ProcKill()
  102. {
  103.     proc_kill(curbuf->b_process, SIGKILL);
  104. }
  105.  
  106. void
  107. ProcInt()
  108. {
  109.     proc_kill(curbuf->b_process, SIGINT);
  110. }
  111.  
  112. void
  113. ProcQuit()
  114. {
  115.     proc_kill(curbuf->b_process, SIGQUIT);
  116. }
  117.  
  118. private void
  119. proc_close(p)
  120. Process    *p;
  121. {
  122.     if (p->p_toproc >= 0) {
  123.         (void) close(p->p_toproc);
  124.         p->p_toproc = -1;    /* writes will fail */
  125.         NumProcs -= 1;
  126.     }
  127. }
  128.  
  129. void
  130. proc_write(p, buf, nbytes)
  131. Process    *p;
  132. char    *buf;
  133. size_t    nbytes;
  134. {
  135.     (void) write(p->p_toproc, buf, nbytes);
  136. }
  137.  
  138.  
  139. #ifdef    STDARGS
  140. private void
  141. proc_strt(char *bufname, int clobber, ...)
  142. #else
  143. private /*VARARGS3*/ void
  144. proc_strt(bufname, clobber, va_alist)
  145.     char    *bufname;
  146.     int    clobber;
  147.     va_dcl
  148. #endif
  149. {
  150.     Window    *owind = curwind;
  151.     int    toproc[2],
  152.         pid;
  153.     Process    *newp;
  154.     Buffer    *newbuf;
  155.     char    *argv[32],
  156.         *cp,
  157.         foo[10],
  158.         cmdbuf[LBSIZE];
  159.     int    i;
  160.     va_list    ap;
  161.  
  162.     isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  163.                    or is of type B_PROCESS */
  164.     if (access(Portsrv, X_OK) < 0) {
  165.         complain("[Couldn't access %s: %s]", Portsrv, strerror(errno));
  166.         /* NOTREACHED */
  167.     }
  168.     dopipe(toproc);
  169.  
  170.     switch (pid = fork()) {
  171.     case -1:
  172.         pipeclose(toproc);
  173.         complain("[Fork failed: %s]", strerror(errno));
  174.  
  175.     case 0:
  176.         argv[0] = "portsrv";
  177.         va_init(ap, clobber);
  178.         make_argv(&argv[1], ap);
  179.         va_end(ap);
  180.         (void) dup2(toproc[0], 0);
  181.         (void) dup2(ProcOutput, 1);
  182.         (void) dup2(ProcOutput, 2);
  183.         pipeclose(toproc);
  184.         jcloseall();
  185.         execv(Portsrv, argv);
  186.         raw_complain("execl failed: %s\n", strerror(errno));
  187.         _exit(1);
  188.     }
  189.  
  190.     newp = (Process *) malloc(sizeof *newp);
  191.     /* ??? better check for newp == NULL -- DHR */
  192.     newp->p_next = procs;
  193.     newp->p_state = NEW;
  194.  
  195.     cmdbuf[0] = '\0';
  196.     va_init(ap, clobber);
  197.     while (cp = va_arg(ap, char *)) {
  198.         size_t    pl = strlen(cmdbuf);
  199.  
  200.         swritef(&cmdbuf[pl], sizeof(cmdbuf)-pl, "%s ", cp);
  201.     }
  202.     va_end(ap);
  203.     va_init(ap, clobber);
  204.     newp->p_name = copystr(cmdbuf);
  205.     procs = newp;
  206.     newp->p_portpid = pid;
  207.     newp->p_pid = -1;
  208.  
  209.     newbuf = do_select((Window *)NULL, bufname);
  210.     newbuf->b_type = B_PROCESS;
  211.     newp->p_buffer = newbuf;
  212.     newbuf->b_process = newp;    /* sorta circular, eh? */
  213.     pop_wind(bufname, clobber, B_PROCESS);
  214.     ToLast();
  215.     if (!bolp())
  216.         LineInsert(1);
  217.     /* Pop_wind() after everything is set up; important!
  218.        Bindings won't work right unless newbuf->b_process is already
  219.        set up BEFORE NEWBUF is first SetBuf()'d. */
  220.     newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
  221.     newp->p_dbx_mode = NO;
  222.  
  223.     newp->p_toproc = toproc[1];
  224.     newp->p_reason = 0;
  225.     NumProcs += 1;
  226.     if (NumProcs == 1)
  227.         (void) kbd_strt();
  228.     (void) close(toproc[0]);
  229.     SetWind(owind);
  230. }
  231.  
  232. void
  233. pinit()
  234. {
  235.     int    p[2];
  236.  
  237.     (void) pipe(p);
  238.     ProcInput = fd_open("process-input", F_READ|F_LOCKED, p[0],
  239.                 (char *)NULL, 512);
  240.     ProcOutput = p[1];
  241.     if ((kbd_pid = fork()) == -1) {
  242.         raw_complain("Cannot fork kbd process! %s\n", strerror(errno));
  243.         finish(SIGHUP);
  244.     }
  245.     if (kbd_pid == 0) {
  246.         signal(SIGINT, SIG_IGN);
  247.         signal(SIGALRM, SIG_IGN);
  248.         close(1);
  249.         dup(ProcOutput);
  250.         jcloseall();
  251.         execl(Kbd_Proc, "kbd", (char *)NULL);
  252.         raw_complain("kbd exec failed: %s\n", strerror(errno));
  253.         exit(-1);
  254.     }
  255. }
  256.  
  257. private int    kbd_state = OFF;
  258.  
  259. /* kbd_strt() and kbd_stop() return true if they changed the state
  260.    of the keyboard process.  E.g., kbd_strt() returns TRUE if the
  261.    kbd process was previously stopped.  This is so kbd starting and
  262.    stopping in pairs works - see finish() in jove.c. */
  263.  
  264. kbd_strt()
  265. {
  266.     if (kbd_state == OFF) {
  267.         kbd_state = ON;
  268.         kill(kbd_pid, KBDSIG);
  269.         return TRUE;
  270.     }
  271.     return FALSE;
  272. }
  273.  
  274. kbd_stop()
  275. {
  276.     if (kbd_state == ON) {
  277.         kbd_state = OFF;
  278.         kill(kbd_pid, KBDSIG);
  279.         return TRUE;
  280.     }
  281.     return FALSE;
  282. }
  283.  
  284. kbd_kill()
  285. {
  286.     if (kbd_pid != 0) {
  287.         kill(kbd_pid, SIGKILL);
  288.         kbd_pid = 0;
  289.     }
  290. }
  291.